#ifndef ORDENADOR_EXTERNO_H_
#define ORDENADOR_EXTERNO_H_

#include"PalabraAleatoria.h"
#include"Heap.h"
#include<fstream>
#include<list>

using std::string;
using std::ifstream;

class OrdenadorExterno{

    private:
        //dos arboles heap usados para ordenar el archivo usando replacement selection
        Heap<PalabraAleatoria>** buffersOrdenamiento;
        /*indica cual de los dos buffers (principal y de congelamiento) es el actual para
        continuar ordenando el archivo */
        short bufferActual;
        PalabraAleatoria* bufferLectura,*bufferEscritura;
        ifstream* archivoEntrada;
        /* tamanios de buffers en terminos de registros de PalabraAleatoria*/
        unsigned int tamanioBufferLectura,tamanioBufferOrdenamiento,tamanioBufferEscritura;
        /*cantidad de palabras aleatorias en archivoEntrada*/
        unsigned long cantidadPalabrasAleatoriasIniciales;
        /*cantidad de registros de PalabraAleatoria restantes en archivo sin ordenar*/
        unsigned long cantidadPalabrasAleatoriasSinOrdenar;
        unsigned int i_runActual;
        /*indice del run actual . Inicia en la letra A= 65*/
        const string NOMBRE_RUN;
        /*nombre generico del directorio donde se almacenaran los runs*/
        const string NOMBRE_DIRECTORIO_RUNS;



        /* internamente se establecen los tamanios de los buffers*/
        void setTamaniosBuffers(unsigned int tamanioBufferLectura);
        /* cambia entre buffer principal y secundario*/
        void alternarBufferOrdenamiento();

        /* en la etapa inicial del replacement selection , el buffer de ordenamiento debe
        llenarse lo mas posible*/
        void llenarBufferOrdenamiento();

        /* ordena el archivo de entrada y genera los runs correspondientes para fusionar en la
        siguiente etapa.*/
        void generarRuns();
        
        /*se completa un paso de la fase de ordenamiento. cpa_bufferLectura indica la cantidad
         de palabras aleatorias cargadas en el buffer de lectura.*/
        void ordenarBuffer(unsigned long cpa_bufferLectura);        
        


    public:
        enum MENSAJE_ORDENAR {ARCHIVO_SALIDA_INVALIDO , EXITO , ARCHIVO_ENTRADA_INVALIDO};
        static const unsigned int TAMANIO_BUFFER_LECTURA_DEFAULT= 10;
        /*guarda magnitud de buffer de ordenamiento en terminos de buffers de lectura. Es decir
        si el buffer de lectura es de n registros y el de ordenamiento es de 10*n registros ->
        MAGNITUD_BUFFER_ORDENAMIENTO= 10*/
        static const unsigned int MAGNITUD_BUFFER_ORDENAMIENTO=10;
        /* ordena el archivo cargado y lo guarda en el archivo de direccion direccionArchivoSalida */
        short ordenar(string direccionArchivoSalida);
        /* crea al objeto archivoEntrada a partir de la direccion direccionArchivoEntrada.
        Si el archivo no puede abrirse se retorna ARCHIVO_ENTRADA_INVALIDO*/
        short setArchivoEntrada(string direccionArchivoEntrada);

        /*crea un objeto OrdenadorExterno se determinan los tamanios  */
        OrdenadorExterno(unsigned int tamBufferLectura);
        ~OrdenadorExterno();

};//OrdenadorExterno

#endif
